package com.ideaaedi.component.decompile.cfr;

import com.google.common.collect.Lists;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.benf.cfr.reader.api.OutputSinkFactory;

import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 源码存储器工厂
 *
 * @author JustryDeng
 * @since 2021/9/23 22:49:47
 */
public class SourceCodeOutputSinkFactory implements OutputSinkFactory {
    
    @Getter
    private final List<String> sourceCodeList;
    
    StringBuilder progressInfo = new StringBuilder();
    
    public SourceCodeOutputSinkFactory(List<String> sourceCodeList) {
        Objects.requireNonNull(sourceCodeList, "sourceCodeList cannot be null.");
        this.sourceCodeList = sourceCodeList;
    }
    
    @Override
    public List<SinkClass> getSupportedSinks(SinkType sinkType, Collection<SinkClass> collection) {
        return Lists.newArrayList(SinkClass.STRING, SinkClass.DECOMPILED, SinkClass.DECOMPILED_MULTIVER,
                SinkClass.EXCEPTION_MESSAGE, SinkClass.LINE_NUMBER_MAPPING);
    }
    
    @Override
    public <T> Sink<T> getSink(SinkType sinkType, SinkClass sinkClass) {
        // sink中的数据都往sourceCode中写
        return sinkable -> {
            // 源码行号信息不需要解析
            if (sinkType == SinkType.LINENUMBER) {
                return;
            }
            // 反编译目标的位置信息
            if (sinkType == SinkType.PROGRESS && sinkable != null) {
                if (StringUtils.isNotBlank(sinkable.toString())) {
                    progressInfo.append("\n").append("// *********************** com.idea-aedi:component-decompile *********************** ");
                    progressInfo.append("\n").append("// ").append(sinkable);
                    progressInfo.append("\n").append("// ********************************************************************************* ");
                }
                return;
            }
            String sourceCode = sinkable == null ? "" : sinkable.toString();
            if (StringUtils.isNotBlank(sourceCode)) {
                String sourceWithProcessInfo = sourceCode + "\n" + progressInfo;
                sourceCodeList.add(sourceWithProcessInfo);
            } else {
                sourceCodeList.add(sourceCode);
            }
            progressInfo.setLength(0);
        };
    }
}
